package listx

import (
	"sort"
	"sync"
)

func NewList() (obj *List) {
	obj = &List{}
	return
}

type List struct {
	data []interface{}

	mutex        sync.RWMutex
	mutexLocked  bool
	mutexRLocked bool
}

func (list *List) rlock() {
	if list.mutexLocked || list.mutexRLocked {
		return
	}
	list.mutex.RLock()
	list.mutexRLocked = true
}
func (list *List) runlock() {
	if !list.mutexRLocked {
		return
	}
	if list.mutexRLocked {
		return
	}
	list.mutex.RUnlock()
	list.mutexRLocked = false
}
func (list *List) lock() {
	if list.mutexLocked || list.mutexRLocked {
		return
	}
	list.mutex.Lock()
	list.mutexLocked = true
}
func (list *List) unlock() {
	if !list.mutexLocked {
		return
	}
	if list.mutexRLocked {
		return
	}
	list.mutex.Unlock()
	list.mutexLocked = false
}

// Add 添加元素, 如果已存在, 不添加
func (list *List) Add(items ...interface{}) {
	list.lock()
	for _, item := range items {
		if list.Contains(item) {
			return
		}
		list.data = append(list.data, item)
	}
	list.unlock()
}

// AddConf 添加元素, 如果已存在相同条件[conf]的项, 不添加
func (list *List) AddConf(cond func(index int, item interface{}) bool, items ...interface{}) {
	list.lock()
	for _, item := range items {
		if list.ContainsCond(cond) {
			return
		}
		list.data = append(list.data, item)
	}
	list.unlock()
}

func (list *List) Set(index int, val interface{}) {
	// 索引的读写是并发安全的
	list.data[index] = val
}

func (list *List) SetList(val []interface{}) {
	list.lock()
	list.data = val
	list.unlock()
}

func (list *List) At(index int) (result interface{}) {
	if index < 0 {
		return
	}
	if index >= list.Length() {
		return
	}
	return list.data[index]
}

func (list *List) Clear() {
	list.lock()
	list.data = []interface{}{}
	list.unlock()
}

func (list *List) Dispose() {
	list.lock()
	list.data = nil
	list.unlock()
}

func (list *List) Clone() *List {
	list.lock()
	s := list.data
	ss := make([]interface{}, len(s), cap(s))
	copy(ss, s)
	list.unlock()
	return &List{data: ss}
}

func (list *List) Contains(item interface{}) bool {
	return list.IndexOf(item) != -1
}

func (list *List) ContainsCond(cond func(index int, item interface{}) bool) bool {
	return list.IndexOfConf(cond) != -1
}

// CountCond 按照条件计数
func (list *List) CountCond(cond func(index int, item interface{}) bool) int {
	list.rlock()
	c := 0
	s := list.data
	for i := 0; i < len(s); i++ {
		if cond(i, s[i]) {
			c++
		}
	}
	list.runlock()

	return c
}

// Every 每一个项都符合条件就返回true
func (list *List) Every(cond func(index int, item interface{}) bool) bool {
	list.lock()
	//defer list.unlock()

	s := list.data
	for i := 0; i < len(s); i++ {
		val := s[i]
		if cond(i, val) == false {
			return false
		}
	}
	list.runlock()
	return true
}

func (list *List) First(cond func(index int, item interface{}) bool) (val interface{}, has bool) {
	list.rlock()
	s := list.data
	for i := 0; i < len(s); i++ {
		v := s[i]
		if cond(i, v) {
			return v, true
		}
	}
	list.runlock()
	return
}

// 返回符合条件的项形成的新列表
func (list *List) Filter(cond func(index int, item interface{}) bool) *List {
	list.rlock()
	var a []interface{}
	for i, x := range list.data {
		if cond(i, x) {
			a = append(a, x)
		}
	}
	list.runlock()
	return &List{data: a}
}

// 如果返回错误，迭代终止
func (list *List) ForRange(handler func(index int, item interface{}) error) {
	list.lock()
	for i, x := range list.data {
		a := x
		if handler(i, a) != nil {
			list.unlock()
			return
		}
	}
	list.unlock()
}

// 从最后往前开始遍历
// 如果返回错误，迭代终止
func (list *List) ForRangeFromLast(handler func(index int, item interface{}) error) {
	list.lock()
	s := list.data
	for i := len(s) - 1; i >= 0; i-- {
		a := s[i]
		if handler(i, a) != nil {
			list.unlock()
			return
		}
	}
	list.unlock()
}

// 返回符合条件的项的索引
func (list *List) IndexOfConf(cond func(index int, item interface{}) bool) int {
	list.rlock()
	s := list.data
	for i := 0; i < len(s); i++ {
		if cond(i, s[i]) {
			return i
		}
	}
	list.runlock()
	return -1
}

// 返回项的索引
func (list *List) IndexOf(item interface{}) int {
	list.rlock()
	s := list.data
	for i := 0; i < len(s); i++ {
		if s[i] == item {
			return i
		}
	}
	list.runlock()
	return -1
}

func (list *List) Last(cond func(index int, item interface{}) bool) (result interface{}, has bool) {
	list.rlock()
	s := list.data
	for i := len(s) - 1; i >= 0; i-- {
		val := s[i]
		if cond(i, val) {
			return val, true
		}
	}
	list.runlock()
	return
}

func (list *List) Length() int {
	return len(list.data)
}

func (list *List) Pop() interface{} {
	list.lock()

	s := list.data
	last := s[len(s)-1] // 索引的读写是并发安全的
	var zero interface{}
	s[len(s)-1] = zero // GC
	s2 := s[:len(s)-1]
	list.data = s2

	list.unlock()
	return last
}

func (list *List) Push(item interface{}) {
	list.lock()
	list.push(item)
	list.unlock()
}

func (list *List) push(item interface{}) {
	list.data = append(list.data, item)
}

func (list *List) PushList(val IList) {
	list.lock()
	list.pushList(val)
	list.unlock()
}

func (list *List) pushList(val IList) {
	s := list.data
	s = append(s, val.Slice()...)
	list.data = s
}

func (list *List) Remove(item interface{}) {
	i := list.IndexOf(item)
	if i != -1 {
		list.RemoveAt(i)
	}
}

func (list *List) RemoveAt(i int) {
	list.lock()

	s := list.data
	copy(s[i:], s[i+1:])
	var zero interface{}
	s[len(s)-1] = zero // GC
	s2 := s[:len(s)-1]
	list.data = s2

	list.unlock()
}

func (list *List) Replace(i int, item interface{}) {
	list.lock()

	s := list.data
	over := i - len(s)
	if over > -1 {
		ss := make([]interface{}, i+1)
		copy(ss[0:], s[:])
		s = ss
	}
	s[i] = item
	list.data = s

	list.unlock()
}

func (list *List) Insert(i int, item interface{}) {
	list.lock()

	s := list.data
	var zero interface{}
	s = append(s, zero /* use the zero value of the element type */)
	copy(s[i+1:], s[i:])
	s[i] = item
	list.data = s

	list.unlock()
}

func (list *List) Reverse() {
	list.lock()

	s := list.data
	for i := len(s)/2 - 1; i >= 0; i-- {
		opp := len(s) - 1 - i
		s[i], s[opp] = s[opp], s[i]
	}

	list.unlock()
}

func (list *List) Shift() interface{} {
	if list.Length() == 0 {
		return nil
	}
	list.lock()

	s := list.data
	top := s[0]
	var zero interface{}
	s[0] = zero // GC
	s2 := s[1:]
	list.data = s2

	list.unlock()
	return top
}

// Slice 直接返回slice值
func (list *List) Slice() []interface{} {
	return list.data
}

// Self 返回自身的列表
// 用于List作为组合时的快捷方式
func (list *List) Self() *List {
	return list
}

// compare返回值：>0 a排b前面
func (list *List) Sort(compare func(a, b interface{}) int) {
	list.lock()
	l := list.data
	sort.Slice(l, func(i, j int) bool {
		return compare(l[i], l[j]) >= 0
	})
	list.unlock()
}

func (list *List) Unshift(item interface{}) {
	list.lock()

	s := list.data
	l := len(s) + 1
	ss := make([]interface{}, l, l)
	ss[0] = item
	copy(ss[1:], s[:])
	list.data = ss

	list.unlock()
}

// Unique 去重操作, 返回去重后的数组
func (list *List) Unique() *List {
	list.lock()
	l := list.unique()
	list.unlock()
	return l
}

func (list *List) unique() *List {
	var r []interface{}
	l := list.data
	m := map[interface{}]struct{}{} // 存放不重复主键
	{
	} // 存放不重复主键
	for _, e := range l {
		length := len(m)
		m[e] = struct{}{}
		if len(m) != length { // 加入map后，map长度变化，则元素不重复
			r = append(r, e)
		}
	}

	return &List{data: r}
}

// UniqueByCustomKey 去重操作, 返回去重后的数组
// 自定义键值
func (list *List) UniqueByCustomKey(getKey func(item interface{}) string) *List {
	list.lock()
	l := list.uniqueByCustomKey(getKey)
	list.unlock()
	return l
}

func (list *List) uniqueByCustomKey(getKey func(item interface{}) string) *List {
	var r []interface{}
	l := list.data
	m := map[string]struct{}{} // 存放不重复主键
	for _, e := range l {
		length := len(m)
		m[getKey(e)] = struct{}{}
		if len(m) != length { // 加入map后，map长度变化，则元素不重复
			r = append(r, e)
		}
	}
	return &List{data: r}
}

// Union 并集
func (list *List) Union(a IList) *List {
	list.lock()
	list.pushList(a)
	l := list.unique()
	list.unlock()
	return l
}

// UnionByCustomKey 并集
func (list *List) UnionByCustomKey(a IList, getKey func(item interface{}) string) *List {
	list.lock()
	list.pushList(a)
	return list.UniqueByCustomKey(getKey)
}
